import re, json

import redis
from django.contrib.auth import login
from django.db.models import Q
from django.http import HttpResponse, JsonResponse

# Create your views here.
from django.views import View
from django_redis import get_redis_connection

from apps.products.models import Product
from apps.users.models import User, Address
from utils.views import LoginRequiredJsonMixin

"""
需求分析：
根据页面的功能（从上到下，从左到右），哪些功能需要和后端配合完成
如何确定哪些功能需要和后端进行交互呢？
    1.经验
    2.关注类似网站的相似功能
"""
"""
1. 判断手机号是否重复的功能
    1.前端：       当用户输入手机号之后，输入框失去焦点，这时前端会向服务器发送一个axios（ajax）请求验证
    2.后端（思路）：
        请求：     接收前端传来的手机号
        业务逻辑：       根据手机号查询数据库，如果查询结果的数量大于0（等于1），则表明手机号已注册过
        业务逻辑：       若查询结果数量等于0，则表明手机号还没有注册过
        响应：     JSON数据  {code:0, count:0/1, errmsg:ok}
        路由：     GET     phone/<phone>/count
        
    3.后端实现步骤：
        1. 接收手机号
        2. 根据手机号查询数据库
        3. 返回响应

2. 用户注册功能实现
    1.前端：       当用户输入 用户名，密码等信息后点击注册按钮进行注册，点击后前端会发送 ajax请求
    2.后端：
        请求：接收前端传来的数据（JSON）
        业务逻辑：   验证数据，数据入库
        响应：     JSON {'code':0, 'errmsg':'ok'}（响应码：0表示成功，400表示失败）
        路由：     POST    register/
        
    3.后端实现步骤：
        1.接收请求（POST-----JSON）
        2.获取数据
        3.验证数据
        4.将数据保存到数据库
        5.返回响应
"""


#     password='wangwu123',
#     username='wangwu666',
#     phone='15690866600',


# 定义对应类视图
class UsernameCountView(View):
    """判断用户名是否重复注册"""

    def get(self, request, username):
        """
        :param request: 请求对象
        :param username: 用户名
        :return: JSON
        """
        count = User.objects.filter(username=username).count()
        return JsonResponse({'code': 0, 'errmsg': 'OK', 'count': count})


class PhoneCountView(View):
    """判断手机号是否重复注册"""

    def get(self, request, phone):
        """
        :param request: 请求对象
        :param phone: 手机号
        :return: JSON
        """
        count = User.objects.filter(phone=phone).count()
        return JsonResponse({'code': 0, 'errmsg': 'OK', 'count': count})


class RegisterView(View):
    def post(self, request):
        # 1.接收请求
        body_byte = request.body
        body_str = body_byte.decode()
        body_dict = json.loads(body_str)
        # 2.获取数据
        username = body_dict.get('username')
        phone = body_dict.get('phone')
        password = body_dict.get('password')
        check_pwd = body_dict.get('check_pwd')
        allow = body_dict.get('allow')
        # 3.验证数据
        # all([xx,xx,xx,...]) all里的元素只要是none，就会返回false
        count = User.objects.filter(phone=phone).count()
        if not all([username, phone, password, check_pwd, allow]):
            return JsonResponse({'code': 400, 'errmsg': '参数信息不全，请填写完整'})
        if not re.match(r'^[\u4e00-\u9fa5a-zA-Z0-9_-]{5,30}$', username):
            return JsonResponse({'code': 400, 'errmsg': '用户名格式错误！'})
        if not re.match(r'^1[345789]\d{9}$', phone):
            return JsonResponse({'code': 400, 'errmsg': '手机号格式错误！'})
        elif not count == 0:
            return JsonResponse({'code': 400, 'errmsg': '手机号已存在！'})
        if not re.match(r'^[0-9A-Za-z]{6,20}$', password):
            return JsonResponse({'code': 400, 'errmsg': '密码格式有误！'})
        if password != check_pwd:
            return JsonResponse({'code': 400, 'errmsg': '两次输入不一致！'})
        if not allow:
            return JsonResponse({'code': 400, 'errmsg': 'allow值错误!'})
        # 4.数据入库
        user = User.objects.create_user(username=username, phone=phone, password=password)
        # 状态保持的实现
        # Django提供了状态保持的方法
        login(request, user)
        # 5.返回响应
        return JsonResponse({'code': 0, 'errmsg': 'ok'})


class CheckImageCodeView(View):
    """检查图形验证码是否输入正确"""

    def get(self, request):
        image_code_user = request.GET.get('image_code')
        uuid = request.GET.get('image_code_id')
        redis_cli = get_redis_connection('code')
        if not all([image_code_user, uuid]):
            return JsonResponse({'code': 401, 'errmsg': '缺少参数'})
        # 获取redis中存储的 uuid 对应的图形验证码
        image_code_redis = redis_cli.get('img_%s' % uuid)
        if image_code_redis is None:
            return JsonResponse({'code': 402, 'errmsg': '图形验证码已过期或不存在'})
        image_code_redis = image_code_redis.decode()
        if image_code_user.lower() != image_code_redis.lower():
            return JsonResponse({'code': 400, 'errmsg': '图形验证码输入错误'})
        return JsonResponse({'code': 0, 'errmsg': '输入正确'})


class LoginView(View):
    """登录"""

    def post(self, request):
        body_str = request.body.decode()
        data = json.loads(body_str)
        account = data.get('account')
        password = data.get('password')
        if not all([account, password]):
            return JsonResponse({'code': 400, 'errmsg': '信息不全或账号不存在'})
        # 验证用户登录时输入的是手机号还是用户名，进而改变用户认证依据的值
        if re.match('1[3-9]\d{9}', account):
            User.USERNAME_FIELD = 'phone'
        else:
            User.USERNAME_FIELD = 'username'
        # 方式2
        # authenticate 传递用户名和密码
        # 如果用户名和密码正确，则返回用户信息  反之返回 null
        from django.contrib.auth import authenticate, login
        user = authenticate(username=account, password=password)
        if user is None:
            return JsonResponse({'code': 400, 'errmsg': '账号或密码错误'})
        login(request, user)
        response = JsonResponse({'code': 0, 'errmsg': '登陆成功'})
        # 前端展示用户名信息
        username = user.username
        response.set_cookie('username', username, max_age=60 * 60 * 24)
        return response


from django.contrib.auth import logout


class LogoutView(View):
    """退出登录"""

    def delete(self, request):
        logout(request)
        response = JsonResponse({'code': 0, 'errmsg': '退出成功，返回登录'})
        response.delete_cookie('username')
        return response


class UserInfoView(LoginRequiredJsonMixin, View):
    """判断用户是否登录以及获取用户信息"""

    def get(self, request):
        info_data = {
            'username': request.user.username,
            'phone': request.user.phone,
            'password': request.user.password
        }
        return JsonResponse({
            'code': 0,
            'errmsg': '登陆成功',
            'info_data': info_data
        })


class ChangeUseInfoView(LoginRequiredJsonMixin, View):
    """修改用户信息"""

    def post(self, request):
        data = json.loads(request.body.decode())
        username = data.get('username')
        newname = data.get('newname')
        newphone = data.get('phone')
        if not newname and not newphone:
            return JsonResponse({'code': 400, 'errmsg': '用户名和手机号不能同时为空'})
        if not newname and newphone:
            count_newphone = User.objects.filter(phone=newphone).count()
            if count_newphone > 0:
                return JsonResponse({'code': 400, 'errmsg': '手机号已被占用'})
            User.objects.filter(username=username).update(phone=newphone)
            return JsonResponse({
                'code': 0,
                'errmsg': '手机号修改成功'
            })
        elif newname and not newphone:
            count_newname = User.objects.filter(username=newname).count()
            if count_newname > 0:
                return JsonResponse({'code': 400, 'errmsg': '用户名已被占用'})
            User.objects.filter(username=username).update(username=newname)
            return JsonResponse({
                'code': 0,
                'errmsg': '用户名修改成功'
            })
        count_newphone = User.objects.filter(phone=newphone).count()
        count_newname = User.objects.filter(username=newname).count()
        if count_newphone > 0:
            return JsonResponse({'code': 400, 'errmsg': '手机号已被占用'})
        elif count_newname > 0:
            return JsonResponse({'code': 400, 'errmsg': '用户名已被占用'})
        User.objects.filter(username=username).update(username=newname, phone=newphone)
        return JsonResponse({
            'code': 0,
            'errmsg': '修改成功'
        })


class ChangePwdView(LoginRequiredJsonMixin, View):
    """修改密码"""

    def put(self, request):
        data_dict = json.loads(request.body.decode())
        old_password = data_dict.get('old_password')
        new_password = data_dict.get('new_password')
        new_password2 = data_dict.get('new_password2')
        if not all([old_password, new_password, new_password2]):
            return JsonResponse({'code': 400, 'errmsg': '参数不全，请检查'})
        result = request.user.check_password(old_password)
        if not result:
            return JsonResponse({'code': 400, 'errmsg': '原始密码输入错误'})
        if not re.match(r'^[0-9A-Za-z]{6,20}$', new_password):
            return JsonResponse({'code': 400, 'errmsg': '新密码要求最少6位，最多20位'})
        if new_password2 != new_password:
            return JsonResponse({'code': 400, 'errmsg': '两次密码输入不一致，请重新输入'})
        try:
            request.user.set_password(new_password)
            request.user.save()
        except Exception as e:
            return JsonResponse({'code': 400, 'errmsg': '修改密码失败'})
        # 密码修改成功后清除用户cookie信息，重定向到登录界面
        logout(request)
        response = JsonResponse({'code': 0, 'errmsg': '修改成功'})
        response.delete_cookie('username')
        return response


class AddressCreateView(LoginRequiredJsonMixin, View):
    """新增地址"""

    def post(self, request):
        count = request.user.addresses.count()
        if count >= 20:
            return JsonResponse({'code': 400, 'errmsg': '超过地址数量上限'})
        data = json.loads(request.body.decode())
        receiver = data.get('receiver')
        province_id = data.get('province_id')
        city_id = data.get('city_id')
        district_id = data.get('district_id')
        place = data.get('place')
        mobile = data.get('mobile')
        user = request.user
        info = {
            'receive': receiver, 'province_id': province_id, 'city_id': city_id, 'district_id': district_id,
            'place': place, 'mobile': mobile
        }
        if not all([receiver, province_id, city_id, district_id, place, mobile]):
            return JsonResponse({'code': 400, "errmsg": '新增缺少必传参数', 'info': info})
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return JsonResponse({'code': 400, "errmsg": '手机号有误'})
        try:
            address = Address.objects.create(
                user=user,
                title=receiver,
                receiver=receiver,
                province_id=province_id,
                city_id=city_id,
                district_id=district_id,
                place=place,
                mobile=mobile
            )
            # 设置默认地址
            if not request.user.default_address:
                request.user.default_address = address
                request.user.save()
        except Exception as e:
            return JsonResponse({'code': 400, 'errmsg': '新增地址失败'})
        address_dict = {
            "id": address.id,
            "title": address.title,
            "receiver": address.receiver,
            "province": address.province.name,
            "city": address.city.name,
            "district": address.district.name,
            "place": address.place,
            "mobile": address.mobile
        }
        return JsonResponse({'code': 0, 'errmsg': '新增地址成功', 'address': address_dict})


class AddressView(LoginRequiredJsonMixin, View):
    """获取地址信息"""

    def get(self, request):
        addresses = Address.objects.filter(user=request.user, is_deleted=False)
        address_list = []
        for site in addresses:
            address_dict = {
                "id": site.id,
                "title": site.title,
                "receiver": site.receiver,
                "province": site.province.name,
                "city": site.city.name,
                "district": site.district.name,
                "place": site.place,
                "mobile": site.mobile
            }
            # 将默认地址移动到最前面
            default_address = request.user.default_address
            if default_address.id == site.id:
                # 查询集 addresses 没有 insert 方法
                address_list.insert(0, address_dict)
            else:
                address_list.append(address_dict)

        default_id = request.user.default_address_id
        return JsonResponse({'code': 0, 'errmsg': 'OK', 'addresses': address_list, 'default_address_id': default_id})


class UpdateDestroyAddressView(LoginRequiredJsonMixin, View):
    """修改地址，删除地址"""

    def put(self, request, id):
        data_dict = json.loads(request.body.decode())
        receiver = data_dict.get('receiver')
        province_id = data_dict.get('province_id')
        city_id = data_dict.get('city_id')
        district_id = data_dict.get('district_id')
        place = data_dict.get('place')
        mobile = data_dict.get('mobile')
        if not all([receiver, province_id, city_id, district_id, place, mobile]):
            return JsonResponse({'code': 400, 'errmsg': '缺少必传参数'})

        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return JsonResponse({'code': 400, 'errmsg': '手机号有误'})
        try:
            Address.objects.filter(id=id).update(
                user=request.user,
                title=receiver,
                receiver=receiver,
                province_id=province_id,
                city_id=city_id,
                district_id=district_id,
                place=place,
                mobile=mobile,
            )
        except Exception as e:
            return JsonResponse({'code': 400, 'errmsg': '地址不存在'})
        address = Address.objects.get(id=id)
        print(address)
        address_dict = {
            "id": address.id,
            "title": address.title,
            "receiver": address.receiver,
            "province": address.province.name,
            "city": address.city.name,
            "district": address.district.name,
            "place": address.place,
            "mobile": address.mobile,
        }
        return JsonResponse({'code': 0, 'errmsg': '修改地址信息成功', 'address': address_dict})

    def delete(self, request, id):
        try:
            address = Address.objects.get(id=id)
            address.is_deleted = True
            address.save()
        except Exception as e:
            return JsonResponse({'code': 400, 'errmsg': '删除地址失败'})


class SetDefaultView(LoginRequiredJsonMixin, View):
    """设置默认地址"""

    def put(self, request, id):
        try:
            address = Address.objects.get(id=id)
            request.user.default_address = address
            request.user.save()
        except Exception as e:
            return JsonResponse({'code': 400, 'errmsg': '设置默认地址失败'})

            # 响应设置默认地址结果
        return JsonResponse({'code': 0, 'errmsg': '设置默认地址成功'})


class UpdateTitleView(LoginRequiredJsonMixin, View):
    def put(self, request, id):
        json_dict = json.loads(request.body.decode())
        title = json_dict.get('title')
        try:
            # 查询地址
            address = Address.objects.get(id=id)
            # 设置新的地址标题
            address.title = title
            address.save()
        except Exception as e:
            return JsonResponse({'code': 400, 'errmsg': '设置地址标题失败'})

        # 4.响应删除地址结果
        return JsonResponse({'code': 0, 'errmsg': '设置地址标题成功'})


class HistoryView(LoginRequiredJsonMixin, View):
    """添加用户浏览记录，存入redis中并获取"""

    def post(self, request):
        user = request.user
        data = json.loads(request.body.decode())
        product_id = data.get('product_id')
        try:
            product = Product.objects.get(product_id=product_id, is_delete=False)
        except Product.DoesNotExist:
            return JsonResponse({'code': 400, 'errmsg': '没有此商品'})
        redis_cli = get_redis_connection('history')
        redis_cli.lrem('history_%s' % user.user_id, 0, product_id)
        redis_cli.lpush('history_%s' % user.user_id, product_id)
        # 对列表进行修剪
        redis_cli.ltrim('history_%s' % user.user_id, 0, 4)
        # redis_cli.execute()
        return JsonResponse({'code': 0, 'errmsg': 'ok'})

    def get(self, request):
        redis_cli = get_redis_connection('history')
        product_ids = redis_cli.lrange('history_%s' % request.user.user_id, 0, -1)
        products = []
        if not product_ids:
            return JsonResponse({'code': 250, 'errmsg': '暂无用户的浏览记录', 'products': products})
        for product_id in product_ids:
            product = Product.objects.get(product_id=product_id, is_delete=False)
            products.append({
                'id': product.product_id,
                'name': product.product_name,
                'image_url': product.img_url,
                'price': product.price,
                'source': product.merchant.merchant_name
            })
        return JsonResponse({'code': 0, 'errmsg': 'ok', 'products': products})


class ShowLikesView(LoginRequiredJsonMixin, View):
    """根据用户浏览记录向用户展示可能感兴趣的商品"""

    def get(self, request):
        global products
        ordering = request.GET.get('ordering')
        redis_cli = get_redis_connection('history')
        product_ids = redis_cli.lrange('history_%s' % request.user.user_id, 0, -1)
        # 判断当前用户是否是新用户，新用户刚登陆是没有历史浏览记录的
        if not product_ids:
            products = Product.objects.filter(is_delete=False).order_by(ordering)[:5]
        else:
            product_types = []
            for product_id in product_ids:
                type_id = Product.objects.get(product_id=product_id).type_id
                product_types.append(int(type_id))
            print(product_types)
            products = Product.objects.filter(
                Q(type_id__in=product_types) & ~Q(product_id__in=product_ids) & Q(sales__gt=80) & Q(
                    is_delete=False)).order_by(ordering)[:5]
        # 根据用户是否有浏览记录做不同推荐
        product_list = []
        for product in products:
            print(product.type)
            product_list.append({
                'id': product.product_id,
                'name': product.product_name,
                'descript': product.description,
                'image_url': product.img_url,
                'price': product.price,
                'sales': product.sales,
                'source': product.merchant.merchant_name
            })
        return JsonResponse({'code': 0, 'errmsg': 'ok', 'like_goods': product_list})
